package gui;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import model.ModelViewLinker;
import model.NetworkModel;

public class FrameView extends JFrame {

	private static final long serialVersionUID = 1L;
	private JMenuBar menu;
	private JMenu file;
	private JMenuItem newFile, open, save, saveas;
	private NetworkView view;

	public FrameView(String header, NetworkModel model) {
		super(header);
		view = new NetworkView(model, this);
		add(view);
		ModelViewLinker.getSingleton().addView(view);
		
		initialize();
	}
	
	public FrameView(String header) {
		super(header);
		view = new NetworkView(this);
		add(view);
		ModelViewLinker.getSingleton().addView(view);
		
		initialize();
		save.setEnabled(false);
		saveas.setEnabled(false);
	}
	
	private void initialize() {
		menu = new JMenuBar();
		file = new JMenu("File");
		newFile = new JMenuItem("New");
		open = new JMenuItem("Open...");
		save = new JMenuItem("Save");
		saveas = new JMenuItem("Save As..");
		
		file.add(newFile);
		file.add(open);
		file.add(save);
		file.add(saveas);
		menu.add(file);
		
		setJMenuBar(menu);
		
		MenuListener listen = new MenuListener();
		newFile.addActionListener(listen);
		open.addActionListener(listen);
		save.addActionListener(listen);
		saveas.addActionListener(listen);
		
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				if(view.getModel() == null) {
					System.exit(0);
				}
				if(view.getModel().unsavedChanges() && view.getModel().numberOfViews() == 1) {
					int choice = 0;
					String filename = view.getModel().getFileName();
					if("Document".equals(filename.substring(0, 8))) {
						filename += ".graph";
						choice = JOptionPane.showConfirmDialog(null, 
							"This document has been modified. Would you like to save this document as " + filename + "?");
						if(choice == JOptionPane.YES_OPTION) {
							view.getModel().setFileName(filename + ".graph");
						}
					}
					else {
						choice = JOptionPane.showConfirmDialog(null, "This document has been modified. Would you like to save it?");
					}
					if(choice == JOptionPane.YES_OPTION) {
						view.getModel().save();
					}
					if(choice != JOptionPane.CANCEL_OPTION) {
						ModelViewLinker.getSingleton().removeView(view.getModel(), view);
						if(ModelViewLinker.getSingleton().numberOfViews() == 0) {
							System.exit(0);
						}
						else {
							System.out.println("Multiple views: save");
							ModelViewLinker.getSingleton().removeModel(view.getModel());
							setVisible(false);
						}
					}
				}
				else if(ModelViewLinker.getSingleton().numberOfViews() == 1) {
					ModelViewLinker.getSingleton().removeView(view.getModel(), view);
					System.exit(0);
				}
				else {
					if(view.getModel().numberOfViews() == 1) {
						ModelViewLinker.getSingleton().removeModel(view.getModel());
					}
					ModelViewLinker.getSingleton().removeView(view.getModel(), view);
					setVisible(false);
				}
			}
		});
		
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		setLocation(150, 100);
		setPreferredSize(new Dimension(900, 600));
		pack();
		setVisible(true);
	}

	private class MenuListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(e.getSource() == newFile) {
				int docSize = 1;
				String filename = "Document " + docSize;
				while(ModelViewLinker.getSingleton().getModel(filename) != null) {
					filename = "Document " + ++docSize;
				}
				NetworkModel model = new NetworkModel(filename);
				ModelViewLinker.getSingleton().addModel(model);
				
				if(view.getModel() == null) {
					setTitle(filename);
					view.addModel(model);
					save.setEnabled(true);
					saveas.setEnabled(true);
				}
				else {
					new FrameView(filename, model);
				}
			}
			else if(e.getSource() == open) {
				JFileChooser fileChooser = new JFileChooser(new File("."));
				FileNameExtensionFilter filter = new FileNameExtensionFilter("Graphs", "graph");
				fileChooser.setFileFilter(filter);
				int returnVal = fileChooser.showDialog(null, "Open...");
				if(returnVal != JFileChooser.APPROVE_OPTION) {
					return;
				}
				String filename = fileChooser.getSelectedFile().getPath();
				NetworkModel model = ModelViewLinker.getSingleton().getModel(filename);
				if(model == null) {
					model = new NetworkModel(filename);
				}
				ModelViewLinker.getSingleton().addModel(model);
				
				if(view.getModel() == null) {
					view.addModel(model);
					setTitle(filename);
					save.setEnabled(true);
					saveas.setEnabled(true);
				}
				else {
					new FrameView(filename, model);
				}
			}
			else if(e.getSource() == save) {
				if("Document".equals(view.getModel().getFileName().substring(0, 8))) {
					JFileChooser fileChooser = new JFileChooser(new File("."));
					FileNameExtensionFilter filter = new FileNameExtensionFilter("Graphs", "graph");
					fileChooser.setFileFilter(filter);
					int returnVal = fileChooser.showDialog(null, "Save");
					if(returnVal != JFileChooser.APPROVE_OPTION) {
						return;
					}
					String filename = fileChooser.getSelectedFile().getPath();
					if(!".graph".equals(filename.substring(filename.length() - 7, filename.length() - 1))) {
						filename += ".graph";
					}
					try {
						//If the filename changes to a used name
						new Scanner(new File(filename));
						
						if(ModelViewLinker.getSingleton().getModel(filename) == null) {
							//Used name is a closed file
							int choice = JOptionPane.showConfirmDialog(null, 
									"There is already a file with this name. Are you sure you want to overwrite this file?", 
									"", JOptionPane.YES_NO_OPTION);
							if(choice == JOptionPane.YES_OPTION) {
								setTitle(filename);
								view.getModel().setFileName(filename);
							}
							else {
								JOptionPane.showMessageDialog(null, "File not saved.");
								return;
							}
						}
						else {
							//Used name is an open file
							int choice = JOptionPane.showConfirmDialog(null, 
									"There are other views editing a file with this name. Are you sure you want to overwrite this file?", 
									"", JOptionPane.YES_NO_OPTION);
							if(choice == JOptionPane.YES_OPTION) {
								
								NetworkModel oldModel = ModelViewLinker.getSingleton().getModel(filename);
								NetworkModel newModel = view.getModel();
								
								ModelViewLinker.getSingleton().updateModel(oldModel, newModel);
								view.getModel().setFileName(filename);
								view.getModel().save();
								setTitle(filename);
							}
							else {
								JOptionPane.showMessageDialog(null, "File not saved.");
								return;
							}
						}
					}
					catch (FileNotFoundException e1) {
						//If the filename changes to an unused name
						setTitle(filename);
						view.getModel().setFileName(filename);
					}
				}
				
				view.getModel().save();
				JOptionPane.showMessageDialog(null, "File was saved.");
			}
			else if(e.getSource() == saveas) {
				JFileChooser fileChooser = new JFileChooser(new File(view.getModel().getFileName()));
				FileNameExtensionFilter filter = new FileNameExtensionFilter("Graphs", "graph");
				fileChooser.setFileFilter(filter);
				int returnVal = fileChooser.showDialog(null, "Save as...");
				if(returnVal != JFileChooser.APPROVE_OPTION) {
					return;
				}
				String filename = fileChooser.getSelectedFile().getPath();
				if(filename.length() < 7 || !".graph".equals(filename.substring(filename.length() - 7, filename.length() - 1))) {
					filename += ".graph";
				}
				
				//If the filename doesn't change, just save it
				if(filename.equals(view.getModel().getFileName())) {
					view.getModel().save();
					JOptionPane.showMessageDialog(null, "File was saved.");
					return;
				}
				try {
					//If the filename changes to a used name
					new Scanner(new File(filename));
					
					if(ModelViewLinker.getSingleton().getModel(filename) == null) {
						//Used name is a closed file
						int choice = JOptionPane.showConfirmDialog(null, 
								"There is already a file with this name. Are you sure you want to overwrite this file?", 
								"", JOptionPane.YES_NO_OPTION);
						if(choice == JOptionPane.YES_OPTION) {
							saveAs(filename);
						}
						else {
							JOptionPane.showMessageDialog(null, "File not saved.");
						}
					}
					else {
						//Used name is an open file
						int choice = JOptionPane.showConfirmDialog(null, 
								"There are other views editing a file with this name. Are you sure you want to overwrite this file?", 
								"", JOptionPane.YES_NO_OPTION);
						if(choice == JOptionPane.YES_OPTION) {
							if(view.getModel().numberOfViews() == 1) {
								ModelViewLinker.getSingleton().removeModel(view.getModel());
							}
							else {
								view.getModel().removeView(view);
							}
							
							NetworkModel oldModel = ModelViewLinker.getSingleton().getModel(filename);
							NetworkModel newModel = new NetworkModel(filename, view.getModel().savedata());
							
							ModelViewLinker.getSingleton().updateModel(oldModel, newModel);
							view.setModel(newModel);
							view.getModel().save();
							setTitle(filename);
							JOptionPane.showMessageDialog(null, "File was saved.");
						}
						else {
							JOptionPane.showMessageDialog(null, "File not saved.");
						}
					}
				}
				catch (FileNotFoundException e1) {
					//If the filename changes to an unused name
					saveAs(filename);
				}
			}
		}
		private void saveAs(String filename) {
			if(view.getModel().numberOfViews() == 1) {
				ModelViewLinker.getSingleton().removeModel(view.getModel());
			}
			view.getModel().removeView(view);
			NetworkModel model = new NetworkModel(filename, view.getModel().savedata());
			view.setModel(model);
			ModelViewLinker.getSingleton().addModel(model);
			view.getModel().save();
			setTitle(filename);
			JOptionPane.showMessageDialog(null, "File was saved.");
		}
	}
}
